public class ext_TransferWonLost {

	Private Opportunity Oppty;
	List<Opportunity> oppyList = new List<Opportunity>();
	List<OppLineWrapper> oppLineList = new List<OppLineWrapper>();
	List<OpportunityLineItem> selectedWonOpps = new List<OpportunityLineItem>();
	List<OpportunityLineItem> selectedLostOpps = new List<OpportunityLineItem>();
	List<OpportunityLineItem> selectedPendingOpps = new List<OpportunityLineItem>();
	List<OpportunityLineItem> OppLineItemCopyWon = new List<OpportunityLineItem>();
	List<OpportunityLineItem> OppLineItemCopyLost = new List<OpportunityLineItem>();
	Map<String, List<OpportunityLineItem>> mapOppLineType = new Map<String, List<OpportunityLineItem>>();
	Map<String, Id> recordTypeMap = new Map<String, Id>();
		
    public ext_TransferWonLost(ApexPages.StandardController controller) {
	 this.Oppty = (Opportunity)controller.getRecord();
    }

	//retreive the close date
	public Opportunity getDateValue() {
		Opportunity mydate = [Select CloseDate from Opportunity where id=: Oppty.Id LIMIT 1];
		return myDate;
	}
		
	//use this or the stock code
	public List<OppLineWrapper> getOppLineItems() {
				oppLineList = new List<OppLineWrapper>();	
				for(OpportunityLineItem o : [SELECT Id, ServiceDate, Line_Item_Status__c, Lost_Reason__c, OpportunityId, PricebookEntry.Name, Discount, Part_Number__c, 
				Description, UnitPrice, Quantity, Total_Amount_Plus_VAT__c, VAT_Value__c,VAT_Code__c,VAT_Rate__c,Commission__c,
				Freight_Rate__c,Duty__c, Margin__c, UOM__c, Delivery_Days__c, Inquiry_Part_No__c, Product_Group__c, 
				Product_Group_Description__c, Product_Group_Master__c, Item_Number__c, NL_Code__c, NL_Code_Description__c   
				 FROM OpportunityLineItem WHERE OpportunityId =: Oppty.id order by Item_Number__c ASC]) {
					oppLineList.add(new OppLineWrapper(o));
				}
			return oppLineList;

	}
	
	
	public class OppLineWrapper {
		public OpportunityLineItem opi {get; set;}
		public Boolean selected {get; set;}
		public String status {get; set;}
		public OppLineWrapper(OpportunityLineItem opps) {
			opi = opps;
		}
	}
	
	public PageReference Next() {
		selectedWonOpps.clear();
		selectedLostOpps.clear();
		selectedPendingOpps.clear();
		
		PageReference opptyPage;
		
		system.debug('size of oppLineList to be processed by Next => ' + oppLineList.size());
		for(OppLineWrapper oppwrapper : oppLineList) {
				system.debug('check status value => ' + oppwrapper.opi.line_item_status__c + ' /id of => ' + oppwrapper.opi.id);
				system.debug('check date value => ' + oppwrapper.opi.ServiceDate + ' /id of => ' + oppwrapper.opi.id);
				//update lost reason for line items				
				if(oppwrapper.opi.line_item_status__c == 'won')	
					selectedWonOpps.add(oppwrapper.opi);
				if(oppwrapper.opi.line_item_status__c == 'lost')	
					selectedLostOpps.add(oppwrapper.opi);
						
		}
		if(selectedWonOpps.size() > 0)		
		mapOppLineType.put('won', selectedWonOpps);//processSelectedApps(selectedWonOpps, 'won');
			
		if(selectedLostOpps.size() > 0)		
		mapOppLineType.put('lost', selectedLostOpps); //processSelectedApps(selectedLostOpps, 'lost');

		if(mapOppLineType.size() > 0) {
			processSelectedApps(mapOppLineType);
		}
		
		
		if(selectedWonOpps.size() > 0)	{	
		opptyPage = new ApexPages.StandardController(oppty).view();
     	opptyPage.setRedirect(true);
     	system.debug('won fires');
		}  
		if(selectedLostOpps.size() >0) {
			Opportunity oppyNew = [SELECT Id, Name, Original_Opportunity_Name__c FROM Opportunity WHERE id=:oppty.id];
			Opportunity lostOppty = [SELECT Id, Name FROM Opportunity WHERE StageName='Closed Lost' AND Name=:oppyNew.Original_Opportunity_Name__c + ' - Lost'];
			opptyPage = new PageReference('/apex/vfp_POSplit_Lost?id=' + lostOppty.id );
			system.debug('lost fires with =>' + lostOppty.Name);
			//final check, if no more line items for this id, delete the record 
			List<OpportunityLineItem> opli = [SELECT Id FROM OpportunityLineItem WHERE OpportunityId =: Oppty.id];
			if(opli.size() == 0) {
				delete oppty;
			}
			//finally delete
			return opptyPage;

		}
		
		//final check, if no more line items for this id, delete the record 
		List<OpportunityLineItem> opli = [SELECT Id FROM OpportunityLineItem WHERE OpportunityId =: Oppty.id];
		Opportunity oppyWon = [SELECT Original_Opportunity_Id__c FROM Opportunity WHERE id=:oppty.id];
		opptyPage = new PageReference('/' + oppyWon.Original_Opportunity_Id__c);
		if(opli.size() == 0) {
			delete oppty;
		}
		
		
		return opptyPage;
	}
	
	
		public void processSelectedApps(Map<String, List<OpportunityLineItem>> maplist) { //public void processSelectedApps(List<OpportunityLineItem> opplist, String status) {
		//get won opp
		//create rollback in case one of the line items fails, rollback everything
		Savepoint sp = Database.setSavepoint();				
		system.debug('process selected method fired');
		Opportunity oppy = [SELECT Id, Name, CurrencyIsoCode, Original_Opportunity_Name__c, Original_Opportunity_Id__c, AccountId,MJB_Sales_Order__c, Initial_Interest__c, Customer_LPO__c, Opportunity_Description__c, Equipment__c, CloseDate,Model__c, Interstart_Delivery_Code__c,Chase_Date__c,Quotation_Date_Time__c,Customer_Reference__c FROM Opportunity WHERE id=:oppty.id];
		Opportunity OrigOpp = [SELECT Id, Opportunity_Won__c, Opportunity_Lost__c FROM Opportunity WHERE Name=:oppy.Original_Opportunity_Name__c + ' - Original'];
		//get record types and assign them on creation
		List<RecordType> recordtypeList = [Select Id, DeveloperName From RecordType  where sobjecttype='Opportunity'];
		
		for(RecordType record: recordTypeList) {
			recordTypeMap.put(record.DeveloperName, record.id);
		}

					
		if(maplist.containsKey('won')) {
				Id wonId;
			if(oppy.Original_Opportunity_Id__c == null) { //create a new won id
			 	//wonOp.OwnerId = UserInfo.getUserId();
			 	Opportunity wonOp = new Opportunity();
			 	if(recordTypeMap.containsKey('Original_Opportunity'))
			 	wonOp.RecordTypeId = recordTypeMap.get('Won_Opportunity');				 	
			 	wonOp.AccountId = oppy.AccountId;
			 	wonOp.MJB_Sales_Order__c = oppy.MJB_Sales_Order__c;
			 	wonOp.Initial_Interest__c = oppy.Initial_Interest__c;
			 	wonOp.Opportunity_Description__c = oppy.Opportunity_Description__c;
			 	wonOp.Equipment__c = oppy.Equipment__c;
			 	wonOp.Customer_LPO__c = oppy.Customer_LPO__c;
			 	wonOp.Model__c = oppy.Model__c;
			 	wonOp.CloseDate = oppy.CloseDate;
			 	wonOp.Name = oppy.Original_Opportunity_Name__c;
			 	wonOp.StageName = 'Closed Won';
			 	wonOp.Interstart_Delivery_Code__c = oppy.Interstart_Delivery_Code__c;
			 	wonOp.Chase_Date__c = oppy.Chase_Date__c;
			 	wonOp.Quotation_Date_Time__c = oppy.Quotation_Date_Time__c;
			 	wonOp.Customer_Reference__c = oppy.Customer_Reference__c;			 	
			 	datetime mydate = datetime.now();
			 	wonOp.Split_Date_and_Time__c = mydate.addSeconds(2);			 	
			 	wonOp.CurrencyIsoCode = oppy.CurrencyIsoCode;
			 	
			 	insert wonOp; //needs to be bulked
			 	wonId = wonOp.id;
			 	oppy.Original_Opportunity_Id__c = wonId;
			 	update oppy;
			 	system.debug('new won record created =>' + wonId);
			 	OrigOpp.Opportunity_Won__c = wonId;
			} else {	
				wonId = oppy.Original_Opportunity_Id__c;
				
			}	
				List<OpportunityLineItem> wonList = mapList.get('won');
			 	
			 	system.debug('trace on wonlist => ' + wonList);
			 	
			 	for(OpportunityLineItem oppLineItem: wonList) {
			 		OpportunityLineItem newOppLine = new OpportunityLineItem(
			 		OpportunityId=wonId, 
			 		PricebookEntryId=oppLineItem.PricebookEntryId, 
			 		Quantity=oppLineItem.Quantity, 
			 		Discount=oppLineItem.Discount, 
			 		UnitPrice=oppLineItem.UnitPrice, 
					Description=oppLineItem.Description, 
					Part_Number__c=oppLineItem.Part_Number__c, 
					VAT_Value__c=oppLineItem.VAT_Value__c, 
					VAT_Code__c=oppLineItem.VAT_Code__c, 
					VAT_Rate__c=oppLineItem.VAT_Rate__c, 
					Commission__c=oppLineItem.Commission__c, 
					Freight_Rate__c=oppLineItem.Freight_Rate__c, 
					Duty__c =oppLineItem.Duty__c, 
					Margin__c=oppLineItem.Margin__c, 
					UOM__c=oppLineItem.UOM__c, 
					Delivery_Days__c=oppLineItem.Delivery_Days__c, 
					Inquiry_Part_No__c=oppLineItem.Inquiry_Part_No__c, 
					Product_Group__c=oppLineItem.Product_Group__c, 
					Product_Group_Description__c=oppLineItem.Product_Group_Description__c, 
					Product_Group_Master__c=oppLineItem.Product_Group_Master__c, 
					Item_Number__c=oppLineItem.Item_Number__c,
					ServiceDate = oppLineItem.ServiceDate,
					NL_Code__c = oppLineItem.NL_Code__c, 
					NL_Code_Description__c = oppLineItem.NL_Code_Description__c  
					
			 		);
			 		system.debug('trace on opplineitem => ' + oppLineItem);
			 		OppLineItemCopyWon.add(newOppLine);
			 	}
			 	
			 	if(OppLineItemCopyWon.size() > 0) {
			 		try{
						system.debug('size of items copied' + OppLineItemCopyWon.size());
					 	insert OppLineItemCopyWon;
					 	system.debug('new opp item created');
					 	delete wonlist;			 	
					} catch (Exception e) {
						//rollback
						Database.rollback(sp);
					}
									 	
			 	}
				
			 
		
		} //end won
		
		
		if(maplist.containsKey('lost')) {
			//query if there is a lost record
			system.debug('value of lost op =>' + oppy.Original_Opportunity_Name__c);	
			List<Opportunity> lostOpQuery = [SELECT Id, Name FROM Opportunity WHERE Name = :oppy.Original_Opportunity_Name__c + ' - Lost' LIMIT 1];
			Opportunity LostOp = new Opportunity();	
			
			system.debug('size of ' + oppy.Original_Opportunity_Name__c  +  ' - lost list =>' + lostOpQuery.size());
			if(lostOpQuery.size() == 0) {
				//create a lost record first 				
			 	if(recordTypeMap.containsKey('Lost_Opportunity'))
			 	LostOp.RecordTypeId = recordTypeMap.get('Lost_Opportunity');
			 	LostOp.AccountId = oppy.AccountId;
			 	LostOp.MJB_Sales_Order__c = oppy.MJB_Sales_Order__c;
			 	LostOp.CloseDate = oppy.CloseDate;
			 	LostOp.Initial_Interest__c = oppy.Initial_Interest__c;
			 	LostOp.Opportunity_Description__c = oppy.Opportunity_Description__c;
			 	LostOp.Equipment__c = oppy.Equipment__c;
			 	LostOp.Model__c = oppy.Model__c;		
			 	LostOp.Customer_LPO__c = oppy.Customer_LPO__c;			 		 	
			 	LostOp.Name = oppy.Original_Opportunity_Name__c + ' - Lost';
			 	LostOp.StageName = 'Closed Lost';
			 	LostOp.Lost_bid_review__c = 'Others';
			 	LostOp.Interstart_Delivery_Code__c = oppy.Interstart_Delivery_Code__c;
			 	LostOp.Chase_Date__c = oppy.Chase_Date__c;
			 	LostOp.Quotation_Date_Time__c = oppy.Quotation_Date_Time__c;
			 	LostOp.Customer_Reference__c = oppy.Customer_Reference__c;					 	
			 	LostOp.CurrencyIsoCode = oppy.CurrencyIsoCode;
			 	insert LostOp; //needs to be bulked
			 	OrigOpp.Opportunity_Lost__c = LostOp.id;
			} else {
				LostOp = lostOpQuery[0];
				system.debug('declared lostOp is =>' + LostOp);	
			}		
							
				
				List<OpportunityLineItem> lostList = mapList.get('lost');
				//insert the lost records
			 	for(OpportunityLineItem oppLineItem: lostList) {
			 		OpportunityLineItem lostOppLine = new OpportunityLineItem(
			 		OpportunityId=LostOp.id, 
			 		PricebookEntryId=oppLineItem.PricebookEntryId, 
			 		Quantity=oppLineItem.Quantity, 
			 		Discount=oppLineItem.Discount, 
			 		UnitPrice=oppLineItem.UnitPrice, 
					Description=oppLineItem.Description, 
					Part_Number__c=oppLineItem.Part_Number__c, 
					VAT_Value__c=oppLineItem.VAT_Value__c, 
					VAT_Code__c=oppLineItem.VAT_Code__c, 
					VAT_Rate__c=oppLineItem.VAT_Rate__c, 
					Commission__c=oppLineItem.Commission__c, 
					Freight_Rate__c=oppLineItem.Freight_Rate__c, 
					Duty__c =oppLineItem.Duty__c, 
					Margin__c=oppLineItem.Margin__c, 
					UOM__c=oppLineItem.UOM__c, 
					Delivery_Days__c=oppLineItem.Delivery_Days__c, 
					Inquiry_Part_No__c=oppLineItem.Inquiry_Part_No__c, 
					Product_Group__c=oppLineItem.Product_Group__c, 
					Product_Group_Description__c=oppLineItem.Product_Group_Description__c, 
					Product_Group_Master__c=oppLineItem.Product_Group_Master__c, 
					Item_Number__c=oppLineItem.Item_Number__c,
					line_item_status__c = 'Lost',
					ServiceDate = oppLineItem.ServiceDate,
					NL_Code__c = oppLineItem.NL_Code__c, 
					NL_Code_Description__c = oppLineItem.NL_Code_Description__c  
										
			 		);
			 		
			 		OppLineItemCopyLost.add(lostOppLine);
			 	}			
			 	
			 	if(OppLineItemCopyLost.size() > 0) {
					
					try{
						system.debug('size of items lost copied => ' + OppLineItemCopyLost.size());
				 		insert OppLineItemCopyLost;
					 	system.debug('lost opp item created');
				 		//delete old list
				 		delete lostlist;		
					} catch (Exception e) {
						//rollback
						Database.rollback(sp);
					}
				 		 	
				 	
			 	}
			
			
		}
		update OrigOpp;
	}
	
	

}